(function ( window ) {

var arr = [],
    push = arr.push,
    slice = arr.slice;

function Itcast ( selector ) {
    return new Itcast.fn.init( selector );
}

Itcast.fn = Itcast.prototype = {
    constructor: Itcast,
    length: 0,
    init: function ( selector ) {
        if ( !selector ) return this;
        if ( typeof selector === 'string' ) {
            if ( /^\s*</.test( selector ) ) {
                push.apply( this, Itcast.parseHTML( selector ));
            } else {
                push.apply( this, Itcast.select( selector ));
            }
            return this;
        }

        if ( selector.nodeType ) {

            this[ 0 ] = selector;
            this.length = 1;
            return this;
        }

        if ( selector.constructor == Itcast ) {

            push.apply( this, selector );
            return this;
        }

    }
};

Itcast.fn.init.prototype = Itcast.fn;

Itcast.extend = Itcast.fn.extend = function ( obj ) {
    for ( var k in obj ) {
        this[ k ] = obj[ k ];
    }
    return this;
};

Itcast.extend({
    select: function ( selector ) {
        return document.querySelectorAll( selector );
    },
    isArrayLike: function ( obj ) {
        if ( Object.prototype.toString.call( obj ) == '[object Array]' ) {
            return true;
        }
        var length = 'length' in obj && obj.length;
        return typeof length === 'number' && length >= 0;
    },
    each: function ( arr, callback ) {
        if ( Itcast.isArrayLike ( arr ) ) {
            for ( var i = 0; i < arr.length; i++ ) {
                if ( callback.call( arr[ i ], i, arr[ i ] ) === false ) break;
            }
        } else {
            for ( var k in arr ) {
                if ( callback.call( arr[ k ], k, arr[ k ] ) === false ) break;
            }
        }
        return arr;
    },
    map: function ( arr, callback ) {
        var newArr = [], tmp;
        if ( Itcast.isArrayLike ( arr ) ) {
            for ( var i = 0; i < arr.length; i++ ) {
                tmp = callback( arr[ i ], i );
                if ( tmp != null ) {
                    newArr.push( tmp );
                }
            }
        } else {
            for ( var k in arr ) {
                tmp = callback( arr[ k ], k );
                if ( tmp != null ) {
                    newArr.push( tmp );
                }
            }
        }
        return newArr;
    },
    insertAfter: function (currentNode,objnode) {
        var nextNode=objnode.nextSibling;
        if(nextNode){
            nextNode.parentNode.insertBefore(currentNode,nextNode);
        }else{
            objnode.parentNode.appendChild(currentNode);
        }
    },
    parseHTML :function ( html ) {
        var  div = document.createElement( 'div' );
        div.innerHTML = html;
        var arr = [];
        for ( var i = 0; i < div.childNodes.length; i++ ) {
            arr.push( div.childNodes[ i ] );
        }
        return arr;
    },
    contains:function(arr,item){
        for(var i=0;i<arr.length;i++){
            if(arr[i]==item){
                return true
            }
        }
        return false;
    },
    unique:function(arr){
        var newArr=[];
        for(var i=0;i<arr.length;i++){
            if(!Itcast.contains(newArr,arr[i])){
                newArr.push(arr[i]);
            }
        }
        return newArr;
    },
    prependChild:function ( currentNode, parentNode ) {
        if ( parentNode.childNodes.length == 0 ) {
            parentNode.appendChild( currentNode );
        } else {
            parentNode.insertBefore( currentNode, parentNode.firstChild );
        }
    },
    prependTo: function ( currentNode, objNode ) {
        if ( objNode.childNodes.length == 0 ) {
            objNode.appendChild( currentNode );
        } else {
            objNode.insertBefore( currentNode, objNode.firstChild );
        }
    },
    appendTo: function ( currentNode, objNode ) {
        objNode.appendChild( currentNode );
    },

});

Itcast.fn.extend({
    each: function ( callback ) {
        return Itcast.each( this, callback );
    },
    map: function ( callback ) {
        return Itcast.map( this, callback );
    },
    toArray: function () {
        return slice.call( this );

    },
    get: function ( index ) {
        if ( index === undefined ) {
            // toArray
            return this.toArray();
        }

        // 正负数
        if ( index < 0 ) {

            return this[ this.length + index ];

        } else {
            return this[ index ];
        }
    },
    first: function (  ) {

        return this.eq( 0 );
    },
    eq: function ( index ) {
        // 获得元素, 并构造 Itcast 对象
        var iobj = this.constructor();

        if ( index == null ) return iobj;

        var dom = this.get( index );
        if ( dom ) {
            iobj[ 0 ] = dom;
            iobj.length = 1; // 由于 iobj 是一个伪数组, 在 元素后应该长度 +1
        }
        return iobj;
    },
    last: function () {
        return this.eq( -1 );
    },
    append:function(selector){
        return this.constructor(selector).appendTo(this);
    },
    end:function(){
        return this.prevObject||this.constructor();
    },
    after:function(selector){
        this.constructor(selector).insertAfter(this);
        return this
    },
    before:function(){
        this.constructor(selector).insertBefore(this);
        return this
    },
    pushStack:function(array){
       var tmp=this.constructor();
        push.apply(tmp,array);
        tmp.prevObject=this;
        return tmp;
    },
    parent:function(){
        return this.pushStack(Itcast.unique(this.map(function(v,i){
            return v.parentNode
        })));
    },
    prepend:function(selector){
        this.constructor(selector).prependTo( this );
        return this;
    },
    prependTo:function(selector){
        var iObj = this.constructor( selector ); // 统一变成伪数组了
        var tmp = [], tmpNode;
        for ( var i = 0; i < this.length; i++ ) {
            for ( var j = 0; j < iObj.length; j++ ) {
                tmpNode = j == iObj.length - 1 ? this[ i ] : this[ i ].cloneNode( true );
                tmp.push( tmpNode );
                Itcast.prependChild( tmpNode, iObj[ j ] );
            }
        }
        var tmpIobj = this.constructor();
        tmpIobj.prevObject = this;
        push.apply( tmpIobj, tmp );
        return tmpIobj;
    },
    insertAfter:function(selector){
        var iobj=this.constructor(selector);
        var tmp=[],tmpNode;
        for(var i=0;i<this.length;i++){
            for(var j=0;j<iobj.length;j++){
                tmpNode=j==iobj.length-1?this[i]:this[i].cloneNode(true);
                tmp.push(tmpNode);
                Itcast.insertAfter(tmpNode,iobj[j])
            }
        }
        var tmpIobj = this.constructor();
        tmpIobj.prevObject = this;
        push.apply( tmpIobj, tmp );
        return tmpIobj;
    },
    insertBefore:function(selector){
        var iobj=this.constructor(selector);
        var tmp=[],tmpNode;
        for(var i=0;i<this.length;i++){
            for(var j=0;j<iobj.length;j++){
                tmpNode=j==iobj.length-1?this[i]:this[i].cloneNode(true)
                tmp.push(tmpNode);
                iobj[j].parentNode.insertBefore(tmp,iobj[j])
            }
        }
        var tmpIobj=this.constructor();
        tmpIobj.prevObject=this;
        push.apply(tmpIobj,tmp);
        return tmpIobj;
    },
    appendTo:function(selector){
        var iObj=this.constructor(selector);
        var tmp=[],tmpNode;
        for(var i=0;i<this.length;i++){
            for(var j=0;j<iObj.length;j++){
                tmpNode=j==iObj.length-1?this[i]:this[i].cloneNode(true);
                tmp.push(tmpNode);
                iObj[j].appendChild(tmpNode);
            }
        }
        var tmpIobj=this.constructor();
        tmpIobj.prevObject=this;
        push.apply(tmpIobj,tmp);
        return tmpIobj;
    },

});


window.Itcast = window.I = Itcast;


})( window );

